/*********************
* Author:Dzlua
* QQ:505544956
* time:2016/05/03
*/
#include "Base.h"
#include <stdlib.h>
#include <string.h>
#include "../utilities/Log.h"

EDUI_NAMESPACE_BEGIN

SystemCursor GetSystemCursorID(const char* name)
{
    if (!name) return SYSTEM_CURSOE_ERROR;
    if (0 == strcmp(name, "arrow")){
        return SYSTEM_CURSOR_ARROW;
    } else if (0 == strcmp(name, "ibeam")){
        return SYSTEM_CURSOR_IBEAM;
    } else if (0 == strcmp(name, "wait")){
        return SYSTEM_CURSOR_WAIT;
    } else if (0 == strcmp(name, "crosshair")){
        return SYSTEM_CURSOR_CROSSHAIR;
    } else if (0 == strcmp(name, "waitarrow")){
        return SYSTEM_CURSOR_WAITARROW;
    } else if (0 == strcmp(name, "sizenwse")){
        return SYSTEM_CURSOR_SIZENWSE;
    } else if (0 == strcmp(name, "sizenesw")){
        return SYSTEM_CURSOR_SIZENESW;
    } else if (0 == strcmp(name, "sizewe")){
        return SYSTEM_CURSOR_SIZEWE;
    } else if (0 == strcmp(name, "sizens")){
        return SYSTEM_CURSOR_SIZENS;
    } else if (0 == strcmp(name, "sizeall")){
        return SYSTEM_CURSOR_SIZEALL;
    } else if (0 == strcmp(name, "no")){
        return SYSTEM_CURSOR_NO;
    } else if (0 == strcmp(name, "hand")){
        return SYSTEM_CURSOR_HAND;
    }
    return SYSTEM_CURSOE_ERROR;
}

//--------------------------------------//

TimerInfo::TimerInfo()
{
#ifdef EDUI_TEST_NEW_DELETE
    Log("[TimerInfo] new timerInfo %d", this);
#endif
}

TimerInfo::~TimerInfo()
{
#ifdef EDUI_TEST_NEW_DELETE
    Log("[TimerInfo] delete timerInfo %d", this);
#endif
}

//--------------------------------------//

void Point::Reset(int _x, int _y)
{
    x = _x;
    y = _y;
}

void PointF::Reset(float _x, float _y)
{
    x = _x;
    y = _y;
}

//--------------------------------------//

void Size::Reset(int _w, int _h)
{
    w = _w;
    h = _h;
}

//--------------------------------------//

void Rect::Reset(int _x,int _y,int _w,int _h)
{
    x = _x;
    y = _y;
    w = _w;
    h = _h;
}

bool Rect::IsInRect(int _x, int _y)
{
    if (_x<=x) return false;
    if (_y<=y) return false;
    if (_x>=x+w) return false;
    if (_y>=y+h) return false;
    return true;
}

bool Rect::IsInRect(Point pt)
{
    if (pt.x<=x) return false;
    if (pt.y<=y) return false;
    if (pt.x>=x+w) return false;
    if (pt.y>=y+h) return false;
    return true;
}

void Rect::Offset(int dx)
{
    x -= dx;
    y -= dx;
    w += 2 * dx;
    h += 2 * dx;
}

void Rect::Union(const Rect* rc)
{
    if (!rc) return;

    int X = x + w;
    int Y = y + h;
    x = rc->x > x ? rc->x : x;
    y = rc->y > y ? rc->y : y;
    X = (rc->x + rc->w) < X ? (rc->x + rc->w) : X;
    Y = (rc->y + rc->h) < Y ? (rc->y + rc->h) : Y;

    w = X - x;
    h = Y - y;

    // no union
    if (x >= X || y >= Y)
    {
        x = 0;
        y = 0;
        w = 0;
        h = 0;
    }
}

bool Rect::IsUnion(const Rect* rc)
{
    if (!rc) return false;
    int X = x + w;
    int Y = y + h;
    int X1 = rc->x > x ? rc->x : x;
    int Y1 = rc->y > y ? rc->y : y;
    X = (rc->x + rc->w) < X ? (rc->x + rc->w) : X;
    Y = (rc->y + rc->h) < Y ? (rc->y + rc->h) : Y;
    if (X1 >= X || Y1 >= Y) return false;
    return true;
}

void Rect::Intersect(const Rect* rc)
{
    if (!rc) return;

    int X = x + w;
    int Y = y + h;
    x = rc->x < x ? rc->x : x;
    y = rc->y < y ? rc->y : y;
    X = (rc->x + rc->w) > X ? (rc->x + rc->w) : X;
    Y = (rc->y + rc->h) > Y ? (rc->y + rc->h) : Y;
    w = X - x;
    h = Y -y;
}

bool Rect::IsOK() const
{
    if ((w <= 0) || (h <= 0)) return false;
    return true;
}

void Rect::Clear() {
    this->Reset(0, 0, 0, 0);
}

//--------------------------------------//
void Rect1::Reset(int _l, int _t, int _r, int _b)
{
    l = _l;
    t = _t;
    r = _r;
    b = _b;
}
//--------------------------------------//

Color::Color(Uint32 col)
{
    a = (col >> 24) & 0xFF;
    r = (col >> 16) & 0xFF;
    g = (col >> 8) & 0xFF;
    b = col & 0xFF;
}

void Color::Reset(Uint8 _r, Uint8 _g, Uint8 _b, Uint8 _a)
{
    r = _r;
    g = _g;
    b = _b;
    a = _a;
}

void Color::Reset(const Color* color)
{
    if (!color) return;
    r = color->r;
    g = color->g;
    b = color->b;
    a = color->a;
}

void Color::Reset(Uint32 col)
{
    a = (col >> 24) & 0xFF;
    r = (col >> 16) & 0xFF;
    g = (col >> 8) & 0xFF;
    b = col & 0xFF;
}

Uint32 Color::Value() const
{
    return (a << 24 | r << 16 | g << 8 | b);
}

//------------------------------------------//

// "false"->false, "true"->true,other->default
bool ParserBool(const char* src, bool bDefault)
{
    if (0 == strcmp(src, "false")){
        return false;
    } else if (0 == strcmp(src, "true")){
        return true;
    }

    return bDefault;
}

//if src is int,fill out,else fill with default. 
bool ParserInt(const char* src, int* out, int bDefault)
{
    char* p = 0;
    (*out) = strtol(src, &p, 10);
    if (!p) (*out) = bDefault;
    return !!p;
}

//error fill point with x,y
Point ParserPoint(const char* src, int x, int y)
{
	Point pt;
	char* p = 0;
	pt.x = strtol(src, &p, 10);
	if (!p) goto error;
	pt.y = strtol(p + 1, &p, 10);
	if (!p) goto error;
	return pt;
error:
	pt.Reset(x, y);
	return pt;
}

//error fill size with w,h
Size ParserSize(const char* src, int w, int h)
{
	Size sz;
	char* p = 0;
	sz.w = strtol(src, &p, 10);
	if (!p) goto error;
	sz.h = strtol(p + 1, &p, 10);
	if (!p) goto error;
	return sz;
error:
	sz.Reset(w, h);
	return sz;
}

//error fill rect with x,y,w,h
Rect ParserRect(const char* src, int x, int y, int w, int h)
{
    Rect rc;
    char* p = 0;
    rc.x = strtol(src, &p, 10);
	if (!p) goto error;
    rc.y = strtol(p + 1, &p, 10);
	if (!p) goto error;
    rc.w = strtol(p + 1, &p, 10);
	if (!p) goto error;
    rc.h = strtol(p + 1, &p, 10);
	if (!p) goto error;
    return rc;
error:
    rc.Reset(x, y, w, h);
    return rc;
}

//error fill rect1 with x,y,w,h
Rect1 ParserRect1(const char* src, int l, int t, int r, int b)
{
    Rect1 rc;
    char* p = 0;
    rc.l = strtol(src, &p, 10);
	if (!p) goto error;
    rc.t = strtol(p + 1, &p, 10);
	if (!p) goto error;
    rc.r = strtol(p + 1, &p, 10);
	if (!p) goto error;
    rc.b = strtol(p + 1, &p, 10);
	if (!p) goto error;
    return rc;
error:
    rc.Reset(l, t, r, b);
    return rc;
}

//error fill Color with argb
Color ParserColor(const char* src, Uint32 argb)
{
    Color col;
    char* p = 0;
    int v = 0;
    if (src[0] == '#') v = strtoul(src + 1, &p, 16);
    else v = strtoul(src, &p, 16);
	if (!p) col.Reset(argb);
    else col.Reset(v);
    return  col;
}

AlignType ParserAlign(const char* src, AlignType align)
{
    if (0 == strcmp(src, "center")) return ALIGN_CENTER;
    else if (0 == strcmp(src, "left")) return ALIGN_LEFT;
    else if (0 == strcmp(src, "lefttop")) return ALIGN_LEFTTOP;
    else if (0 == strcmp(src, "top")) return ALIGN_TOP;
    else if (0 == strcmp(src, "righttop")) return ALIGN_RIGHTTOP;
    else if (0 == strcmp(src, "right")) return ALIGN_RIGHT;
    else if (0 == strcmp(src, "rightbottom")) return ALIGN_RIGHTBOTTOM;
    else if (0 == strcmp(src, "bottom")) return ALIGN_BOTTOM;
    else if (0 == strcmp(src, "leftbottom")) return ALIGN_LEFTBOTTOM;
    return align;
}

WndFullScreen ParserWndFullScreen(const char* src, WndFullScreen type)
{
    if (0 == strcmp(src, "windowed")) return WND_FULLSCREEN_WINDOWED;
    else if (0 == strcmp(src, "real")) return WND_FULLSCREEN_REAL;
    else if (0 == strcmp(src, "desktop")) return WND_FULLSCREEN_DESKTOP;
    return type;
}

// get the character number of utf8 string.
Uint32 UTF8_CharNumber(const char* str)
{
    Uint32 rlen = 0;
    Uint32 instrlen = (Uint32)strlen(str);
    for (Uint32 i = 0, len = 0; i < instrlen; i += len){
        Uint8 byte = str[i];
        if (byte >= 0xFC) len = 6;
        else if (byte >= 0xF8) len = 5;
        else if (byte >= 0xF0) len = 4;
        else if (byte >= 0xE0) len = 3;
        else if (byte >= 0xC0) len = 2;
        else len = 1;
        ++rlen;
    }
    return rlen;
}

// get the index character's position and length in string.return false if out of range.
bool UTF8_QueryChar(const char* str, Uint32 index, Uint32* pos, Uint32* inlen)
{
    Uint32 rlen = 0;
    Uint32 instrlen = (Uint32)strlen(str);
    for (Uint32 i = 0, len = 0; i < instrlen; i += len){
        Uint8 byte = str[i];
        if (byte >= 0xFC) len = 6;
        else if (byte >= 0xF8) len = 5;
        else if (byte >= 0xF0) len = 4;
        else if (byte >= 0xE0) len = 3;
        else if (byte >= 0xC0) len = 2;
        else len = 1;
        ++rlen;

        if (index == rlen){
            *pos = i;
            *inlen = len;
            return true;
        }
    }
    return false;
}

EDUI_NAMESPACE_END
